#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/slab.h>

#if 0
    backlight {
		compatible = "pwm-backlight";
		pwms = <&pwm1 0 5000000>;
		brightness-levels = <0 4 8 16 32 64 128 255>;
		default-brightness-level = <6>;
		status = "okay";
	};
#endif
/**
 * 模块入口
 */
static int __init dtsof_init(void)
{
    int ret = 0;
    struct device_node *blnd = NULL;  //节点
    struct property *comppro = NULL;  // 属性
    const char *str = NULL;
    u32 value;
    u32 elemsize;
    u32 *brival = NULL;
    u8 i = 0;

    /* 1、找到backlight节点，路径是：/backlighti */
    blnd = of_find_node_by_path("/backlight");
    if(blnd == NULL)  /* 失败 */
    {
        printk("No /backlight node !\n");
		ret = -EINVAL;
        goto failfindnd;
    }

    /* 2、获取属性 */
     comppro = of_find_property(blnd, "compatible", NULL);  //获取字符串信息
     if(comppro == NULL)  /* 失败 */
     {
         ret = -EINVAL;
         goto failfindpro;
     }
     else  /* 成功 */
     {
         printk("compatible = %s \r\n", (char *)comppro->value);
     }

     ret = of_property_read_string(blnd, "status", &str);
    if(ret < 0)
    {
        goto fail_readstr;
    }
    else
    {
        printk("status = %s \r\n", str);
    }

    /* 3、获取数字值 */
    ret = of_property_read_u32(blnd, "default-brightness-level", &value);
    if(ret < 0)
    {
        goto fail_read32;
    }
    else
    {
        printk("default-brightness-level = %d \r\n", value);
    }

    /* 4、获取数组的属性 */
    elemsize = of_property_count_elems_of_size(blnd, "brightness-levels", sizeof(u32));
    if(elemsize < 0)
    {
        ret = -EIO;
        goto fail_readele;
    }
    else
    {
        printk("brightness-levels elems of size: %d \r\n", elemsize);
    }

    brival = kmalloc(elemsize * sizeof(u32), GFP_KERNEL);  // 动态申请内存空间
    if(brival == NULL)
    {
        printk("%s: kmalloc failed \r\n", __func__);
        ret = -EIO;
        goto fail_mem;
    }
    // 获取数组元素
    ret = of_property_read_u32_array(blnd, "brightness-levels", brival, elemsize);
    if(ret < 0)
    {
        goto fail_read32arry;
    }
    else
    {
        for(i = 0; i < elemsize; i++)
        {
            printk("brightness-levels[%d] = %d\r\n", i, *(brival++));
        }
        kfree(brival);
    }

    return 0;

fail_read32arry:
    kfree(brival);
fail_mem:
fail_read32:
fail_readele:
fail_readstr:
failfindpro:
failfindnd:
    return ret;
}

/**
 * 模块入口和出口
 */
static void __exit dtsof_exit(void)
{

}

/**
 * 注册模块入口和出口
 */
module_init(dtsof_init);
module_exit(dtsof_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("george <g_yubo@163.com>");
